/*********************************************************
*Copyright (c) 2009 Rob Groves. All Rights in Pw 
*@des: 异步并发TCP client
*@name: client.cpp
*@author: zhongsx
*@time: 2015-02-27
*********************************************************/
#include "client.h"
#include "ClientMgr.h"
#include <boost/lexical_cast.hpp>

client::client(boost::asio::io_service& ios, CallBack_T _func)
	:socket_(ios), func_(_func), io_service_(ios), timer_(ios)
{
	read_buf_ = boost::shared_ptr<message>(new message());
	sta = CONNCT;
	type = SESSION;
}


client::client(boost::asio::io_service& ios, CallBack_T func, std::string ip, short port)
	:func_(func), io_service_(ios), socket_(ios), timer_(ios)
{  
	//1
 //	boost::system::error_code error = boost::asio::error::host_not_found;  
// 	boost::asio::ip::address add;  
// 	add.from_string(ip);  
// 	boost::asio::ip::tcp::endpoint endpoint_(add, port);  
	//2
// 	std::string sport = boost::lexical_cast<std::string>(port);
// 	boost::asio::ip::tcp::resolver resolver_(io_service_); 
// 	boost::asio::ip::tcp::resolver::query query_(ip, sport); //输入ip（或域名）和端口号  
// 	boost::asio::ip::tcp::resolver::iterator iterator = resolver_.resolve(query_);
// 	boost::asio::ip::tcp::endpoint endpoint_ = *iterator;

	//所有的操作都采用异步的方式 
	sta = CLOSE;
	type = CLIENT;

	read_buf_ = boost::shared_ptr<message>(new message());
	socket_.async_connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(ip), port), 
			boost::bind(&client::handle_connect, this, _1));
	//socket_.async_connect(endpoint_, boost::bind(&client::handle_connect, this, _1)); 
// 	//30秒超时处理
	timer_.expires_from_now(boost::posix_time::seconds(30));
 	timer_.async_wait(boost::bind(&client::time_out, this,_1));
}  

client::~client()
{
	timer_.cancel();
}

boost::asio::ip::tcp::socket& client::socket()
{
	return socket_;
}

void client::start_read()
{
	read_buf_->reset();
	//读取数据报头 
	boost::asio::async_read(socket_,  
		boost::asio::buffer(read_buf_->header(), message::header_length), 
		boost::bind(&client::handle_read_header, this, _1, _2));  
	//
	timer_.expires_from_now(boost::posix_time::seconds(10));
	//timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(10)); 
	timer_.async_wait(boost::bind(&client::time_out, this, _1));
}

void client::write(boost::shared_ptr<message> msg)  
{  
	//将消息主动投递给io_service  
	io_service_.post(boost::bind(&client::do_write, this, msg)); 
}  

void client::close()  
{
	//读数据失败时调用    
	//这个close函数是客户端要主动终止时调用  do_close函数是从服务器端  
	io_service_.post(boost::bind(&client::do_close, this)); 
}  

void client::handle_connect(const boost::system::error_code& error)  
{  
	if (!error){  
		start_read();
		sta = CONNCT;
	} 
	else{
		errstr = error.message(); 
	}
}  

void client::handle_read_header(const boost::system::error_code& error, int bytes_)  
{  
	//分别处理数据报头和数据部分  
	if (!error) {  
		//处理数据头,获取body数据长度
		if (bytes_ == message::header_length){
			//msgHead_Main* head = read_bufs_->decode_header();
			int blen = read_buf_->body_length();
			//异步读取指定长度hlen的body数据
			boost::asio::async_read(socket_, boost::asio::buffer(read_buf_->body(), blen),	
				boost::bind(&client::handle_read_msg, this, _1, _2));

			//
			timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(10));  
			timer_.async_wait(boost::bind(&client::time_out, this, _1));
		}
		else{
			start_read();
		}
	}  
	else  {
		errstr = error.message();
	}  
}  

void client::handle_read_msg(const boost::system::error_code& error, int bytes_)  
{  
	if (!error){
		if (bytes_ == read_buf_->body_length()){
			boost::shared_ptr<client> pClient = this->shared_from_this();

			func_(pClient, read_buf_);
		}
		//继续
		start_read();
	}  
	else{  
		errstr = error.message();
	}  
}  

void client::do_write(boost::shared_ptr<message> msg)  
{
	bool write_in_progress = !write_bufs_.empty(); //空的话变量为false  
	write_bufs_.push_back(msg); //把要写的数据push至写队列  
	if (!write_in_progress)//队列初始为空 push一个msg后就有一个元素了  
	{  
		boost::shared_ptr<message> buf = write_bufs_.front();
		// 
 		boost::asio::async_write(socket_, boost::asio::buffer(buf->data(), buf->length()), 
 			boost::bind(&client::handle_write, this, _1));  		
	}  
}  

//第一个消息单独处理，剩下的才更好操作  
void client::handle_write(const boost::system::error_code& error)
{  
 	if (!error){  
 		write_bufs_.pop_front();//刚才处理完一个数据 所以要pop一个  
  		if (!write_bufs_.empty())    
  		{          		
    		//循环处理剩余的消息 
			boost::shared_ptr<message> buf = write_bufs_.front();
			// 
			boost::asio::async_write(socket_, boost::asio::buffer(buf->data(), buf->length()),
				boost::bind(&client::handle_write, this, _1));  	 		
  		}  
	}  
	else{  
		errstr = error.message();
		std::cout<<errstr<<std::endl;

	}  
}  

void client::do_close()  
{  
	socket_.shutdown(boost::asio::socket_base::shutdown_both);
	sta = CLOSE;
	boost::shared_ptr<client> pClient = this->shared_from_this();
	ClientMgr::GetClietMgr()->pop(pClient);
	//socket_.close(); 
} 

void client::time_out(const boost::system::error_code& error)
{
	if (!error){
		errstr = "连接30秒内未响应, 关闭连接";
		do_close();
	}
}